home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / mint / mint104s.zoo / mint.src / debug.c < prev    next >
C/C++ Source or Header  |  1993-03-08  |  14KB  |  620 lines

  1. /*
  2. Copyright 1990,1991,1992 Eric R. Smith.
  3. Copyright 1992 Atari Corporation.
  4. All rights reserved.
  5. */
  6.  
  7. /* MiNT debugging output routines */
  8. /* also, ksprintf is put here, for lack of any better place to put it */
  9.  
  10. #include "mint.h"
  11. #include <stdarg.h>
  12.  
  13. static void VDEBUGOUT P_((int, const char *, va_list));
  14.  
  15. /*
  16.  * ksprintf implements a very crude sprintf() function that provides only
  17.  * what MiNT needs...
  18.  *
  19.  * NOTE: this sprintf probably doesn't conform to any standard at
  20.  * all. It's only use in life is that it won't overflow fixed
  21.  * size buffers (i.e. it won't try to write more than SPRINTF_MAX
  22.  * characters into a string)
  23.  */
  24.  
  25. static int
  26. PUTC(char *p, int c, int *cnt, int width) {
  27.     int put = 1;
  28.  
  29.     if (*cnt <= 0) return 0;
  30.     *p++ = c;
  31.     *cnt -= 1;
  32.     while (*cnt > 0 && --width > 0) {
  33.         *p++ = ' ';
  34.         *cnt -= 1;
  35.         put++;
  36.     }
  37.     return put;
  38. }
  39.  
  40. static int
  41. PUTS(char *p, const char *s, int *cnt, int width) {
  42.     int put = 0;
  43.  
  44.     if (s == 0) s = "(null)";
  45.  
  46.     while (*cnt > 0 && *s) {
  47.         *p++ = *s++;
  48.         put++;
  49.         *cnt -= 1;
  50.         width--;
  51.     }
  52.     while (width-- > 0 && *cnt > 0) {
  53.         *p++ = ' ';
  54.         put++;
  55.         *cnt -= 1;
  56.     }
  57.     return put;
  58. }
  59.  
  60. static int
  61. PUTL(char *p, unsigned long u, int base, int *cnt, int width, int fill_char)
  62. {
  63.     int put = 0;
  64.     static char obuf[32];
  65.     char *t;
  66.  
  67.     t = obuf;
  68.  
  69.     do {
  70.         *t++ = "0123456789ABCDEF"[u % base];
  71.         u /= base;
  72.         width--;
  73.     } while (u > 0);
  74.  
  75.     while (width-- > 0 && *cnt > 0) {
  76.         *p++ = fill_char;
  77.         put++;
  78.         *cnt -= 1;
  79.     }
  80.     while (*cnt > 0 && t != obuf) {
  81.         *p++ = *--t;
  82.         put++;
  83.         *cnt -= 1;
  84.     }
  85.     return put;
  86. }
  87.  
  88. int
  89. vksprintf(char *buf, const char *fmt, va_list args)
  90. {
  91.     char *p = buf, c, fill_char;
  92.     char *s_arg;
  93.     int i_arg;
  94.     long l_arg;
  95.     int cnt;
  96.     int width, long_flag;
  97.  
  98.     cnt = SPRINTF_MAX - 1;
  99.     while( (c = *fmt++) != 0 ) {
  100.         if (c != '%') {
  101.             p += PUTC(p, c, &cnt, 1);
  102.             continue;
  103.         }
  104.         c = *fmt++;
  105.         width = 0;
  106.         long_flag = 0;
  107.         fill_char = ' ';
  108.         if (c == '0') fill_char = '0';
  109.         while (c && isdigit(c)) {
  110.             width = 10*width + (c-'0');
  111.             c = *fmt++;
  112.         }
  113.         if (c == 'l' || c == 'L') {
  114.             long_flag = 1;
  115.             c = *fmt++;
  116.         }
  117.         if (!c) break;
  118.  
  119.         switch (c) {
  120.         case '%':
  121.             p += PUTC(p, c, &cnt, width);
  122.             break;
  123.         case 'c':
  124.             i_arg = va_arg(args, int);
  125.             p += PUTC(p, i_arg, &cnt, width);
  126.             break;
  127.         case 's':
  128.             s_arg = va_arg(args, char *);
  129.             p += PUTS(p, s_arg, &cnt, width);
  130.             break;
  131.         case 'd':
  132.             if (long_flag) {
  133.                 l_arg = va_arg(args, long);
  134.             } else {
  135.                 l_arg = va_arg(args, int);
  136.             }
  137.             if (l_arg < 0) {
  138.                 p += PUTC(p, '-', &cnt, 1);
  139.                 width--;
  140.                 l_arg = -l_arg;
  141.             }
  142.             p += PUTL(p, l_arg, 10, &cnt, width, fill_char);
  143.             break;
  144.         case 'o':
  145.             if (long_flag) {
  146.                 l_arg = va_arg(args, long);
  147.             } else {
  148.                 l_arg = va_arg(args, unsigned int);
  149.             }
  150.             p += PUTL(p, l_arg, 8, &cnt, width, fill_char);
  151.             break;
  152.         case 'x':
  153.             if (long_flag) {
  154.                 l_arg = va_arg(args, long);
  155.             } else {
  156.                 l_arg = va_arg(args, unsigned int);
  157.             }
  158.             p += PUTL(p, l_arg, 16, &cnt, width, fill_char);
  159.             break;
  160.         case 'u':
  161.             if (long_flag) {
  162.                 l_arg = va_arg(args, long);
  163.             } else {
  164.                 l_arg = va_arg(args, unsigned int);
  165.             }
  166.             p += PUTL(p, l_arg, 10, &cnt, width, fill_char);
  167.             break;
  168.  
  169.         }
  170.     }
  171.     *p = 0;
  172.     return (int)(p - buf);
  173. }
  174.  
  175. int ARGS_ON_STACK 
  176. ksprintf(char *buf, const char *fmt, ...)
  177. {
  178.     va_list args;
  179.     int foo;
  180.  
  181.     va_start(args, fmt);
  182.     foo = vksprintf(buf, fmt, args);    
  183.     va_end(args);
  184.     return foo;
  185. }
  186.  
  187. int debug_level = 1;    /* how much debugging info should we print? */
  188. int out_device = 2;    /* BIOS device to write errors to */
  189.  
  190. /*
  191.  * out_next[i] is the out_device value to use when the current
  192.  * device is i and the user hits F3.
  193.  * Cycle is CON -> PRN -> AUX -> MIDI -> 6 -> 7 -> 8 -> 9 -> CON
  194.  * (Note: BIOS devices 6-8 exist on Mega STe and TT, 9 on TT.)
  195.  *
  196.  * out_device and this table are exported to bios.c and used here in HALT().
  197.  */
  198.  
  199. /*            0  1  2  3  4  5  6  7  8  9 */
  200. char out_next[] = { 1, 3, 0, 6, 0, 0, 7, 8, 9, 2 };
  201.  
  202. /*
  203.  * debug log modes:
  204.  *
  205.  * 0: no logging.
  206.  * 1: log all messages, dump the log any time something happens at
  207.  *    a level that gets shown.  Thus, if you're at debug_level 2,
  208.  *    everything is logged, and if something at levels 1 or 2 happens,
  209.  *    the log is dumped.
  210.  *
  211.  * LB_LINE_LEN is 20 greater than SPRINTF_MAX because up to 20 bytes
  212.  * are prepended to the buffer string passed to ksprintf.
  213.  */
  214.  
  215. #define LBSIZE 50                /* number of lines */
  216. #define LB_LINE_LEN (SPRINTF_MAX+20)        /* width of a line */
  217. int debug_logging;
  218. int logptr;
  219. static char logbuf[LBSIZE][LB_LINE_LEN];
  220. static short logtime[LBSIZE];    /* low 16 bits of 200Hz: timestamp of msg */
  221.  
  222. /*
  223.  * Extra terse settings - don't even output ALERTs unless asked to.
  224.  *
  225.  * Things that happen in on an idle Desktop are at LOW_LEVEL:
  226.  * Psemaphore, Pmsg, Syield.
  227.  */
  228.  
  229. #define FORCE_LEVEL 0
  230. #define ALERT_LEVEL 1
  231. #define DEBUG_LEVEL 2
  232. #define TRACE_LEVEL 3
  233. #define LOW_LEVEL 4
  234.  
  235. /*
  236.  * The inner loop does this: at each newline, the keyboard is polled. If
  237.  * you've hit a key, then it's checked: if it's ctl-alt, do_func_key is
  238.  * called to do what it says, and that's that.  If not, then you pause the
  239.  * output.  If you now hit a ctl-alt key, it gets done and you're still
  240.  * paused.  Only hitting a non-ctl-alt key will get you out of the pause. 
  241.  * (And only a non-ctl-alt key got you into it, too!)
  242.  *
  243.  * When out_device isn't the screen, number keys give you the same effects
  244.  * as function keys.  The only way to get into this code, however, is to
  245.  * have something produce debug output in the first place!  This is
  246.  * awkward: Hit a key on out_device, then hit ctl-alt-F5 on the console so
  247.  * bios.c will call DUMPPROC, which will call ALERT, which will call this.
  248.  * It'll see the key you hit on out_device and drop you into this loop.
  249.  * CTL-ALT keys make BIOS call do_func_key even when out_device isn't the
  250.  * console.
  251.  */
  252.  
  253. void
  254. debug_ws(s)
  255.     const char *s;
  256. {
  257.     long key;
  258.     int scan;
  259.     int stopped;
  260.  
  261.     while (*s) {
  262.     (void)Bconout(out_device, *s);
  263.     while (*s == '\n' && out_device != 0 && Bconstat(out_device)) {
  264.         stopped = 0;
  265.         while (1) {
  266.         /* got a key; if ctl-alt then do it */
  267.         key = Bconin(out_device);
  268.         if (out_device == 2) {
  269.             if ((Kbshift(-1) & 0x0c) == 0x0c) {
  270.             scan = (int) (((key >> 16) & 0xff));
  271.             do_func_key(scan);
  272.             }
  273.             else goto ptoggle;
  274.         }
  275.         else {
  276.             if (key < '0' || key > '9') {
  277. ptoggle:        /* not a func key */
  278.             if (stopped) break;
  279.             else stopped = 1;
  280.             }
  281.             else {
  282.             /* digit key from debug device == Fn */
  283.             if (key == '0') scan = 0x44;
  284.             else scan = (int) (key - '0' + 0x3a);
  285.             do_func_key(scan);
  286.             }
  287.         }
  288.         }
  289.     }
  290.     s++;
  291.     }
  292. }
  293.  
  294. /*
  295.  * _ALERT(s) returns 1 for success and 0 for failure.
  296.  * It attempts to write the string to "the alert pipe," u:\pipe\alert.
  297.  * If the write fails because the pipe is full, we "succeed" anyway.
  298.  *
  299.  * This is called in vdebugout and also in memprot.c for memory violations.
  300.  * It's also used by the Salert() system call in dos.c.
  301.  */
  302.  
  303. int
  304. _ALERT(s)
  305. char *s;
  306. {
  307.     FILEPTR *f;
  308.     char alertbuf[SPRINTF_MAX+10], *ptr, *lastspace;
  309.     int counter;
  310.     char *alert;
  311.     int olddebug = debug_level;
  312.     int oldlogging = debug_logging;
  313.  
  314. /* temporarily reduce the debug level, so errors finding
  315.  * u:\pipe\alert don't get reported
  316.  */
  317.     debug_level = debug_logging = 0;
  318.     f = do_open("u:\\pipe\\alert",(O_WRONLY | O_NDELAY),0,(XATTR *)0);
  319.     debug_level = olddebug;
  320.     debug_logging = oldlogging;
  321.  
  322.     if (f) {
  323. /*
  324.  * format the string into an alert box
  325.  */
  326.     if (*s == '[') {    /* already an alert */
  327.         alert = s;
  328.     } else {
  329.         alert = alertbuf;
  330.         ksprintf(alertbuf, "[1][%s", s);
  331. /*
  332.  * make sure no lines exceed 30 characters; also, filter out any
  333.  * reserved characters like '[' or ']'
  334.  */
  335.         ptr = alertbuf+4;
  336.         counter = 0;
  337.         lastspace = 0;
  338.         while(*ptr) {
  339.             if (*ptr == ' ') {
  340.                 lastspace = ptr;
  341.             } else if (*ptr == '[') {
  342.                 *ptr = '(';
  343.             } else if (*ptr == ']') {
  344.                 *ptr = ')';
  345.             } el